<?php
namespace ImWorker;

/**
 * 配置类
 * @author YeWJ <yeweijian299@163.com>
 * @date 2016-07-06 11:43:22
 */
class Config
{
    protected $_overwrite;
    protected $_data = [];

    public function __construct(array $data = [], $overwrite = false)
    {
        $this->_overwrite = (boolean) $overwrite;
        $this->_data      = $data;
    }

    public function get($name = null, $default = null, $delimiter = '.')
    {
        if (null === $name) {
            return $this->_data;
        }
        if (false === strpos($name, $delimiter)) {
            return isset($this->_data[$name]) ? $this->_data[$name] : $default;
        }
        $name = explode($delimiter, $name);
        $ret  = $this->_data;
        foreach ($name as $key) {
            if (!isset($ret[$key])) {
                return $default;
            }

            $ret = $ret[$key];
        }
        return $ret;
    }

    public function __get($name)
    {
        return $this->get($name);
    }

    public function set($name, $value, $delimiter = '.')
    {
        $pos = &$this->_data;
        if (!is_string($delimiter) || false === strpos($name, $delimiter)) {
            $key = $name;
        } else {
            $name = explode($delimiter, $name);
            $cnt  = count($name);
            for ($i = 0; $i < $cnt - 1; $i++) {
                if (!isset($pos[$name[$i]])) {
                    $pos[$name[$i]] = [];
                }

                $pos = &$pos[$name[$i]];
            }
            $key = $name[$cnt - 1];
        }
        if (!$this->_overwrite && isset($pos[$key])) {
            throw new ImWorkerException('this name of config is read only');
        } else {
            $pos[$key] = $value;
        }
    }

    public function __set($name, $value)
    {
        $this->set($name, $value);
    }

    public function __isset($name)
    {
        return isset($this->_data[$name]);
    }

    public function __unset($name)
    {
        if ($this->_overwrite) {
            unset($this->_data[$name]);
        } else {
            throw new ImWorkerException('Cola_Config is read only');
        }
    }

    public function keys()
    {
        return array_keys($this->_data);
    }

    public function overwrite($overwrite = null)
    {
        if (null === $overwrite) {
            return $this->_overwrite;
        }

        $this->_overwrite = $overwrite;
        return $this;
    }
    public function merge($config)
    {
        $this->_data = $this->_merge($this->_data, $config);
        return $this;
    }
    protected function _merge($arr1, $arr2)
    {
        foreach ($arr2 as $key => $value) {
            if (isset($arr1[$key]) && is_array($value)) {
                $arr1[$key] = $this->_merge($arr1[$key], $arr2[$key]);
            } else {
                $arr1[$key] = $value;
            }
        }
        return $arr1;
    }
    public function &reference()
    {
        return $this->_data;
    }
}
